﻿using Newtonsoft.Json;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Zocono.Infrastructure.Common;
using Zocono.WCS.Domain.DomainRepository;
using Zocono.WCS.Domain.EntityInfo;
using Zocono.WCS.Domain.LogDomain;
using Zocono.WCS.Domain.PlcBytesObject;
using Zocono.WCS.Domain.PlcConnectPoolDomain;
using Zocono.WCS.Domain.ProcessModuleDomain;
using Zocono.WCS.Infrastructure.ApllicationDto.Enums;
using Zocono.WCS.WMSApiDomain.WebApi;

namespace Zocono.WCS.Domain.EquipmentProcessDomain.PlanarGeneralMessage
{
    public class UnBindingService : IPlanarGeneralPlcActionProcessService
    {
        private readonly IRedisHelper _IRedisHelper;
        private readonly ILogUtil _LogUtil;
        private readonly IPlcConnectionPool _PlcConnectionPool; 
        private readonly IPlcWriteDbInfoRepository _PlcWriteDbInfoRepository;
        private readonly IPlcConnectionStateInfoRepository _IPlcConnectionStateInfoRepository;
        private readonly IRunLogInfoService _IRunLogInfoService;
        private readonly IWorkTaskInfoRepository _WorkTaskInfoRepository;

        public UnBindingService(IRedisHelper iRedisHelper, ILogUtil logUtil
           , IPlcConnectionPool plcConnectionPool
            , IPlcWriteDbInfoRepository plcWriteDbInfoRepository
            , IWorkTaskInfoRepository workTaskInfoRepository
             , IPlcConnectionStateInfoRepository plcConnectionStateInfoRepository
            , IRunLogInfoService runLogInfoService)
        {
            _IRedisHelper = iRedisHelper;
            _LogUtil = logUtil;
            _PlcConnectionPool = plcConnectionPool;
            _PlcWriteDbInfoRepository = plcWriteDbInfoRepository;
            _IPlcConnectionStateInfoRepository = plcConnectionStateInfoRepository;
            _IRunLogInfoService = runLogInfoService;
            _WorkTaskInfoRepository = workTaskInfoRepository;
        }
        public  async Task ProcessActionMessageAsync(BytesObjectBase plcActionMessage, BytesObjectBase wcsActionMessage, EquipmentDbObject planarEquipmentDbObject)
        {
            var plcMessage = plcActionMessage as PlanarGeneralPlcActionBO;//Plc的动作报文
            var wcsMessage = wcsActionMessage as PlanarGeneralWcsActionBO;//Wcs的动作报文
            plcMessage.PalletBarcode = plcMessage.PalletBarcode.Trim();

            RunLogInfo runLogInfo = new()
            {
                ContainerBarcode = plcMessage.PalletBarcode,
                EquipmentCode = plcMessage.EquipmentCode,
                RunType = "托盘解绑",
                RunLog = "托盘解绑任务开始"
            };


            //未执行（待执行）
            //执行中
            //4. 组织报文，写入plc
            var objectType = typeof(PlanarGeneralWriteWcsAction).Name;
            var writeConfig = await _PlcWriteDbInfoRepository.GetFirstAsync(it => it.EquipmentCode == plcMessage.EquipmentCode && it.ObjectType == objectType);
            if (writeConfig == null)
            {
                //runLogInfo.RunLog = $"获取PLC写入配置失败";
                //await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                //return;
                _LogUtil.Error($"托盘解绑业务：获取PLC设备【{plcMessage.EquipmentCode}】写入配置失败！请检查读DB配置！");
                return;
            }


            //plc报文什么握手类型则回什么握手类型
            PlanarGeneralWriteWcsAction writeBo = new PlanarGeneralWriteWcsAction(
                writeConfig.PlcConnectionId,
                writeConfig.ID,
                writeConfig.DbCode,
                writeConfig.DbStart,
                objectType,
                plcMessage.EquipmentCode.ToInt32(),
                0,
                //toEquiment.ToInt32(),
                plcMessage.ToEquipmentCode,
                plcMessage.TaskCode,
                plcMessage.PalletBarcode,
                plcMessage.PalletType,
                0);

            //托盘类型
            switch (plcMessage.PalletBarcode.Substring(1, 1))
            {
                case "A":
                    writeBo.PalletType = 2;
                    break;
                case "B":
                    writeBo.PalletType = 1;
                    break;
                case "C":
                    writeBo.PalletType = 3;
                    break;
            }
            var plcConn = _PlcConnectionPool.S7GetWritePlcConnection(writeBo.PlcConnectionID);
            if (plcConn == null)
            {
                //runLogInfo.RunLog = $"获取连接({writeBo.PlcConnectionID})失败";
                //await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                //return;
                _LogUtil.Error($"托盘解绑业务：设备【{plcMessage.EquipmentCode}】获取PLC写入连接({plcMessage.PlcConnectionID})失败");
                return;
            }
            var plcIPStates = await _IPlcConnectionStateInfoRepository.GetFirstAsync(l => l.PlcConnectionID == plcMessage.PlcConnectionID && l.Connected == true);
            if (plcIPStates == null)
            {
                //runLogInfo.RunLog = $"{plcConn.IP}plc已离线";
                //await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                //return;
                _LogUtil.Error($"托盘解绑业务：设备【{plcMessage.EquipmentCode}】离线：{plcConn.IP}plc已离线");
                return;
            }
            //if (plcMessage.AlrmCode != 0)
            //{
            //    runLogInfo.RunLog = $"报警,报警代码：{plcMessage.AlrmCode}";
            //    await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
            //    return;
            //}

            //校验plc信息是否有托盘码
            if (string.IsNullOrEmpty(plcMessage.PalletBarcode) || plcMessage.PalletBarcode.Length != 10)
            {
                writeBo.AlrmCode = 102;
                writeBo.ActionType = 99;
                var flag = await plcConn.WriteDbAsync(writeBo.DbCode, writeBo.DbStart, writeBo.Deserialize());
                _IRedisHelper.SetStringKey($"PLC-{plcMessage.EquipmentCode}", plcMessage.EquipmentCode.ToString() + plcMessage.AlrmCode, TimeSpan.FromSeconds(10));
                return;
            }

            //3. 验证wcs任务，验证wcs当前子任务
            if (plcMessage.EquipmentCode != "110123")
            {
                var exp = Expressionable.Create<WorkTaskInfo>();
                exp.AndIF(true, it => it.PalletCode == plcMessage.PalletBarcode &&it.TaskCode==plcMessage.TaskCode&&it.TaskState==EnumTaskState.Finish);
                var task = await _WorkTaskInfoRepository.GetFirstAsync(exp.ToExpression());
                if (task == null)
                {
                    _LogUtil.Error($"托盘解绑业务：托盘码【{plcMessage.PalletBarcode}】任务号({plcMessage.TaskCode})执行中的任务数据异常查找不到数据");

                    writeBo.AlrmCode = 114;
                    writeBo.ActionType = 99;
                    var flag = await plcConn.WriteDbAsync(writeBo.DbCode, writeBo.DbStart, writeBo.Deserialize());
                    _IRedisHelper.SetStringKey($"PLC-{plcMessage.EquipmentCode}", plcMessage.EquipmentCode.ToString() + plcMessage.AlrmCode, TimeSpan.FromSeconds(10));
                    return;
                }
            }
            //开始解绑
            try
            {
                WMSApiDomain.WebApi.HeaderResult<bool> result = await WCSMessageWithWMSApi.UnbandingContainerAsync(plcMessage.PalletBarcode,plcMessage.EquipmentCode, 0);
                if (result.IsSucceed)
                {
                    //runLogInfo.RunLog = $"PLC写入报文内容： {JsonConvert.SerializeObject(writeBo)}";
                    //await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                    writeBo.ActionType = plcMessage.ActionType;
                    var writeResult = await plcConn.WriteDbAsync(writeBo.DbCode, writeBo.DbStart, writeBo.Deserialize());
                    if (writeResult == false)
                    {
                        _LogUtil.Error($"托盘解绑业务：托盘码【{plcMessage.PalletBarcode}】解绑成功，解绑设备【{plcMessage.EquipmentCode}】PLC(IP{plcConn.IP},写入报文失败");
                        return;
                    }
                    runLogInfo.RunLog = $"托盘解绑业务：托盘码【{plcMessage.PalletBarcode}】解绑成功，解绑设备号【{plcMessage.EquipmentCode}】PLC写入成功！报文内容： {JsonConvert.SerializeObject(writeBo)}";
                    await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                    //runLogInfo.RunLog = "解绑成功";
                    //await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                }
                else
                {
                    writeBo.ActionType = 15;//解绑失败
                    writeBo.AlrmCode = 13;
                    var writeResult = await plcConn.WriteDbAsync(writeBo.DbCode, writeBo.DbStart, writeBo.Deserialize());
                    if (writeResult == false)
                    {
                        _LogUtil.Error($"托盘解绑业务：托盘码【{plcMessage.PalletBarcode}】解绑失败！解绑设备【{plcMessage.EquipmentCode}】PLC(IP{plcConn.IP},写入报文失败");
                        return;
                    }
                    
                    runLogInfo.RunLog = $"托盘解绑业务：托盘码【{plcMessage.PalletBarcode}】解绑失败，解绑设备号【{plcMessage.EquipmentCode}】PLC写入成功！报文内容： {JsonConvert.SerializeObject(writeBo)}";
                    //await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                    _LogUtil.Error(runLogInfo.RunLog);
                }
            }
            catch 
            {
                _LogUtil.Error($"托盘解绑业务：托盘码【{plcMessage.PalletBarcode}】任务号({plcMessage.TaskCode})解绑报错！");

                writeBo.AlrmCode = 13;
                writeBo.ActionType = 99;
                var flag = await plcConn.WriteDbAsync(writeBo.DbCode, writeBo.DbStart, writeBo.Deserialize());
                _IRedisHelper.SetStringKey($"PLC-{plcMessage.EquipmentCode}", plcMessage.EquipmentCode.ToString() + plcMessage.AlrmCode, TimeSpan.FromSeconds(10));
                return;
            }


        }
    }
}
